use std::collections::HashMap;

#[derive(Debug,Default,Clone)]
pub struct Input {
    ctx:HashMap<String,String>,
}

impl Input {
    pub fn store<K:ToString,V:ToString>(&mut self,key:K,val:V){
        let key = key.to_string();
        let key = key.trim_start_matches("-").to_string();
        self.ctx.insert(key,val.to_string());
    }
    pub fn raw_load(&mut self,key:&str)->Option<String>{

        let key = key.to_string();
        let key = key.trim_start_matches("-");

        self.ctx.remove(key)
    }
    pub fn load<T:std::str::FromStr>(&mut self,key:&str)->Option<T>{
        let s = self.raw_load(key)?;
        match s.parse() {
            Ok(o)=>Some(o),
            Err(_)=>None,
        }
    }
}

#[cfg(test)]
mod test{
    use crate::context::Input;

    #[derive(Debug,PartialEq)]
    struct Val{
        name:String
    }
    impl std::str::FromStr for Val{
        type Err = ();

        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(Self{name:s.to_string()})
        }
    }

    #[test]
    fn test_context(){
        let mut ctx = Input::default();
        ctx.store("hello","world");
        ctx.store("key1",1usize);
        ctx.store("key2",true);
        ctx.store("key3","context");

        assert_eq!("world".to_string(),ctx.load::<String>("hello").unwrap());
        assert_eq!(1isize,ctx.load::<isize>("key1").unwrap());
        assert_eq!(true,ctx.load::<bool>("key2").unwrap());
        assert_eq!(Val{name:"context".to_string()},ctx.load::<Val>("key3").unwrap());
        assert_eq!(None,ctx.load::<isize>("key4"));
    }
}